package ai.people.platform.system.service.impl;

import ai.people.core.security.support.RequestHolderUtil;
import ai.people.netmon.framework.domain.system.entity.NmSystemRole;
import ai.people.netmon.framework.domain.system.entity.NmSystemRoleUser;
import ai.people.netmon.framework.domain.system.request.AddSystemRoleRequest;
import ai.people.netmon.framework.domain.system.request.SysRoleRequest;
import ai.people.netmon.framework.domain.system.request.UpdateSystemRoleRequest;
import ai.people.netmon.framework.exception.enums.AccountExceptionEnum;
import ai.people.netmon.framework.exception.enums.CommonEnum;
import ai.people.netmon.framework.exception.enums.SystemExceptionEnum;
import ai.people.netmon.framework.model.response.PageResponse;
import ai.people.netmon.framework.utils.AssertUtils;
import ai.people.netmon.utils.NumeralPool;
import ai.people.platform.system.mapper.SystemRoleMapper;
import ai.people.platform.system.service.SysRoleUserService;
import ai.people.platform.system.service.SystemRoleService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * 系统角色服务impl
 *
 * @author yuanqinglong
 * @date 2022/3/7 11:08
 */
@Service
@RefreshScope
public class SystemRoleServiceImpl extends ServiceImpl<SystemRoleMapper, NmSystemRole> implements SystemRoleService {

    /**
     * 系统角色映射器
     */
    @Autowired
    private SystemRoleMapper systemRoleMapper;

    /**
     * 系统用户角色服务
     */
    @Autowired
    private SysRoleUserService sysRoleUserService;

    /**
     * 顶级角色id标记
     */
    @Value("${role.top.parentId}")
    private Long roleParentId;


    /**
     * 角色列表
     *
     * @param request 请求
     * @return {@link PageResponse}<{@link NmSystemRole}>
     */
    @Override
    public PageResponse<NmSystemRole> listRoles(SysRoleRequest request) {
        Page<NmSystemRole> page = new Page<>(request.getOriginPageNo(), request.getPageSize());
        LambdaQueryWrapper<NmSystemRole> query = request.createQuery();
        Page<NmSystemRole> result = page(page, query);
        return PageResponse.builder(result);
    }

    /**
     * 通过id获取角色
     *
     * @param id id
     * @return {@link NmSystemRole}
     */
    @Override
    public NmSystemRole getRolesById(Long id) {
        NmSystemRole systemRole = this.getById(id);
        AssertUtils.isNotNull(systemRole, SystemExceptionEnum.ROLE_DOES_NOT_EXIST);
        return systemRole;
    }

    /**
     * 用户角色
     *
     * @param userId 用户id
     * @return {@link List}<{@link NmSystemRole}>
     */
    @Override
    public List<NmSystemRole> userRoles(Long userId) {
        List<NmSystemRole> nmSysRoles = systemRoleMapper.listRolesByUserId(userId);
        AssertUtils.isFalse(CollectionUtils.isEmpty(nmSysRoles), AccountExceptionEnum.ACCOUNT_IS_NOT_ASSIGNED_A_ROLE);
        return nmSysRoles;
    }

    /**
     * 保存角色
     *
     * @param addSystemRoleRequest 添加系统角色请求
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRoles(AddSystemRoleRequest addSystemRoleRequest) {
        NmSystemRole nmSystemRole = JSONObject.parseObject(JSONObject.toJSONString(addSystemRoleRequest), NmSystemRole.class);
        this.checkRoleInfo(nmSystemRole);
        LambdaQueryWrapper<NmSystemRole> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.select(NmSystemRole::getId).eq(NmSystemRole::getName, addSystemRoleRequest.getName());
        List<NmSystemRole> nmSystemRoles = systemRoleMapper.selectList(lambdaQuery);
        AssertUtils.isTrue(nmSystemRoles.isEmpty(), SystemExceptionEnum.DUPLICATE_ROLE_NAME);
        nmSystemRole.setCreateUserId(RequestHolderUtil.getUserId());

        boolean save = this.save(nmSystemRole);
        AssertUtils.isTrue(save, CommonEnum.FAIL);
    }


    /**
     * 更新角色
     *
     * @param updateSystemRoleRequest 更新系统角色请求
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRoles(UpdateSystemRoleRequest updateSystemRoleRequest) {
        this.getRolesById(updateSystemRoleRequest.getId());
        NmSystemRole nmSystemRole = JSONObject.parseObject(JSONObject.toJSONString(updateSystemRoleRequest), NmSystemRole.class);
        this.checkRoleInfo(nmSystemRole);
        LambdaQueryWrapper<NmSystemRole> lambdaQuery = Wrappers.lambdaQuery(NmSystemRole.class);
        lambdaQuery.select(NmSystemRole::getId).eq(NmSystemRole::getName, nmSystemRole.getName()).ne(NmSystemRole::getId, nmSystemRole.getId());
        List<NmSystemRole> nmSystemRoles = systemRoleMapper.selectList(lambdaQuery);
        AssertUtils.isTrue(nmSystemRoles.isEmpty(), SystemExceptionEnum.DUPLICATE_ROLE_NAME);
        nmSystemRole.setUpdateTime(LocalDateTime.now());
        boolean updateResult = this.updateById(nmSystemRole);
        AssertUtils.isTrue(updateResult, CommonEnum.FAIL);
    }

    /**
     * 更新启用
     *
     * @param roleId  角色id
     * @param enabled 启用
     */
    @Override
    public void updateEnabled(Long roleId, Boolean enabled) {
        this.checkRoleExists(roleId);
        NmSystemRole systemRole = this.getRolesById(roleId);
        systemRole.setUpdateTime(LocalDateTime.now());
        systemRole.setIsEnable(enabled ? NumeralPool.ONE : NumeralPool.ZERO);
        systemRoleMapper.updateById(systemRole);
    }

    /**
     * 删除角色
     *
     * @param roleId id
     */
    @Override
    public void deleteRoles(Long roleId) {
        this.checkRoleExists(roleId);
        List<NmSystemRoleUser> roleUserList = sysRoleUserService.selectRoleUserByRoleId(roleId);
        AssertUtils.isTrue(roleUserList.isEmpty(), SystemExceptionEnum.ROLE_IN_USE);
        boolean removeResult = this.removeById(roleId);
        AssertUtils.isTrue(removeResult, CommonEnum.FAIL);
    }

    /**
     * 检查角色存在
     *
     * @param roleId 角色id
     */
    @Override
    public void checkRoleExists(Long roleId) {
        NmSystemRole nmSystemRole = systemRoleMapper.selectById(roleId);
        AssertUtils.isTrue(Objects.nonNull(nmSystemRole),SystemExceptionEnum.ROLE_DOES_NOT_EXIST);
    }


    /**
     * 检查角色信息
     *
     * @param role 角色
     */
    private void checkRoleInfo(NmSystemRole role) {
        if (Objects.isNull(role.getParentId())) {
            role.setParentId(roleParentId);
        }
        if (!Objects.equals(roleParentId, role.getParentId())) {
            LambdaQueryWrapper<NmSystemRole> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.select(NmSystemRole::getId).eq(NmSystemRole::getId, role.getParentId());
            List<NmSystemRole> nmSystemRoles = systemRoleMapper.selectList(lambdaQuery);
            AssertUtils.isFalse(nmSystemRoles.isEmpty(), SystemExceptionEnum.PARENT_ROLE_DOES_NOT_EXIST);
        }
    }

}
